/*
 * Alloy Analyzer
 * Copyright (c) 2004 Massachusetts Institute of Technology
 *
 * The Alloy Analyzer is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * The Alloy Analyzer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the Alloy Analyzer; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package alloy.gui;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.text.BadLocationException;
import javax.swing.text.Keymap;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;

import alloy.api.SolutionData;
import alloy.util.Dbg;
import alloy.util.ParameterEvent;
import alloy.util.ParameterListener;
import alloy.util.Params;

class EvalWindow extends AlloyWindow {
    private static final String REGULAR = "regular";
    private static final String PROMPT = "prompt";
    private static final String SOLUTION = "solution";
    private static final String ERROR = "error";

    private alloy.api.AlloyEvaluator ae;
    private JTextPane console;

    private ParameterListener fontUpdater;

    EvalWindow(String title, SolutionData instance) {
	super(title);

	ae = new alloy.api.AlloyEvaluator(instance);

	console = new JTextPane(new ConsoleDocument());
	console.setFont(Params.glob.getFontParam("GUI", "textfont"));

	fontUpdater = new ParameterListener() {
		public void valueChanged(ParameterEvent e) {
		    console.setFont(Params.glob.getFontParam("GUI", "textfont"));
		}
	    };
	Params.glob.addParameterListener("GUI","textfont",fontUpdater);

	getContentPane().add(
			     new JScrollPane(
					     console,
					     JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
					     JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
	initConsoleStyles();

	initConsoleActions();

	prompt();

    }

    private void write(String str, String style) {
	ConsoleDocument doc = (ConsoleDocument)console.getDocument();
	try {
	    doc.insertString(doc.getLength(), str, console.getStyle(style));
	}
	catch (BadLocationException ble) {
	    Dbg.fatal(ble.getMessage(), ble);
	}

	doc.readOnlyBeforeCurrent();
    }

    private void prompt() {
	write("\nEVAL>", PROMPT);
	write(" ", REGULAR);
    }

    private void initConsoleStyles() {

	Style def = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);

	Style regular = console.addStyle(REGULAR, def);

	Style s = console.addStyle(PROMPT, regular);
	StyleConstants.setBold(s, true);
	//StyleConstants.setForeground(s,Color.blue);

	s = console.addStyle(ERROR, regular);
	StyleConstants.setBold(s, true);
	StyleConstants.setForeground(s, Color.red);

	s = console.addStyle(SOLUTION, regular);
	StyleConstants.setBold(s, true);
	//StyleConstants.setForeground(s, Color.green);

    }

    private void initConsoleActions() {
	Keymap km = console.getKeymap();
	KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);

	Action action = new AbstractAction() {
                public void actionPerformed(ActionEvent e) {
                    ConsoleDocument doc = (ConsoleDocument)console.getDocument();
                    int _startOff = doc.getWritableOffset();
                    int _length = doc.getLength() - _startOff;
                    try {

                        String sol = ae.evaluate(console.getText(_startOff, _length));

                        if (Dbg.userError)
                            write("\nERROR> ", ERROR);
                        else
                            write("\nSOLUTION> ", SOLUTION);

                        write(sol, REGULAR);

                    }
                    catch (BadLocationException ble) {
                        Dbg.fatal(ble.getMessage(), ble);
                    }

                    prompt();
                }
            };

	km.addActionForKeyStroke(ks, action);
    }

    public void dispose() {
        ae.cleanup();
	Params.glob.removeParameterListener("GUI","textfont",fontUpdater);
	super.dispose();
    }
}

